#pragma once

#include <string>
#include <fstream>
#include <sstream>
#include <unordered_map>
#include <functional>
#include "Log.h"
#include "Socket.h"

#define Sep "\r\n"

namespace zmh
{
#define Http_BLANKSPACE " "
#define Http_NEWLINE "\r\n"
#define Http_SEPARATOR ": "
#define Http_WebRoot "./Webroot"
#define Http_Def_Index "./Webroot/index.html"

    class Request // 客户端的请求
    {
    public:
        Request() = default;
        void Deserialize(const std::string &data)
        {
            std::cout << data << std::endl;

            std::istringstream iss(data);
            // 解析: 请求行
            {
                std::string buffer;
                std::getline(iss, buffer);
                if (buffer.back() == '\r') // 因为iss只会过滤\n与空格
                    buffer.pop_back();
                std::istringstream iss(buffer);
                iss >> _method;
                iss >> _uri;
                iss >> _version;
                _uri = _uri == "/" ? Http_Def_Index : Http_WebRoot + _uri;
            }
            // 解析: 请求报头
            while (true)
            {
                std::string buffer;
                std::getline(iss, buffer);
                if (buffer.back() == '\r')
                    buffer.pop_back();
                if (!buffer.size())
                    break;
                int pos = buffer.find(Http_SEPARATOR);
                if (pos == std::string::npos) // 读不到？只能是出错了,读取到垃圾请求
                {
                    LOG(zmh::WARNING) << "Request请求格式不正确";
                    return;
                }
                _header[buffer.substr(0, pos)] = buffer.substr(pos + sizeof(Http_SEPARATOR));
            }
            // 解析: 正文
            iss >> _data;
        }
        std::string Serialize() const
        {
            // step1 --- 请求行
            std::string ret = _method + Http_BLANKSPACE + _uri + Http_BLANKSPACE + _version + Http_NEWLINE;
            // step2 --- 请求报头
            for (auto &[key, value] : _header)
                ret += key + Http_SEPARATOR + value + Http_NEWLINE;
            // step3 --- 空行
            ret += _blankline;
            // step3 --- 正文
            ret += _data;
            return ret;
        }
        std::string get_uri() { return _uri; }

    private:
        std::string _method;                                  // 方法
        std::string _uri;                                     // 统一资源标识符
        std::string _version;                                 // 版本号
        std::unordered_map<std::string, std::string> _header; // 请求报头
        std::string _blankline = Http_NEWLINE;                // 空行
        std::string _data;                                    // 正文
    };
    class Response // 服务端的回应
    {
    public:
        Response() = default;
        void init_version(const std::string &version)
        {
            _version = version;
        }
        void init_status(int status)
        {
            switch (status)
            {
            case 200:
                _status = status;
                _describe = "OK";
                break;
            case 404:
                _status = status;
                _describe = "Not Found";
                break;
            case 302:
                _status = status;
                _describe = "See Other";
            default:
                break;
            }
        }
        void init_data(const std::string &data)
        {
            _data = data;
        }
        void init_header(const std::string &key, const std::string &value)
        {
            _header[key] = value;
        }
        void Deserialize(std::string data)
        {
            // std::cout << "#####################################################################################" << std::endl;
            std::istringstream iss(data);
            // 解析: 请求行
            {
                std::string buffer;
                std::getline(iss, buffer);
                if (buffer.back() == 'r')
                    buffer.pop_back();
                std::istringstream iss(buffer);
                // LOG(zmh::DEBUG) << buffer;
                iss >> _version;
                iss >> _status;
                iss >> _describe;
            }
            // 解析: 请求报头
            while (true)
            {
                std::string buffer;
                std::getline(iss, buffer);
                if (buffer.back() == 'r')
                    buffer.pop_back();
                if (!buffer.size())
                    break;
                // LOG(zmh::DEBUG) << buffer;
                int pos = buffer.find(Http_SEPARATOR);
                if (pos == std::string::npos) // 读不到？只能是出错了,读取到垃圾请求
                {
                    LOG(zmh::WARNING) << "Request请求格式不正确";
                    return;
                }
                _header[buffer.substr(0, pos)] = buffer.substr(pos + sizeof(Http_SEPARATOR));
            }
            // 解析: 正文
            iss >> _data;
            // std::cout << "#####################################################################################" << std::endl;
        }
        std::string Serialize()
        {
            // step1 --- 状态行
            std::string ret = _version + Http_BLANKSPACE + std::to_string(_status) + Http_BLANKSPACE + _describe + Http_NEWLINE;
            // step2 --- 请求报头
            for (auto &[key, value] : _header)
                ret += key + Http_SEPARATOR + value + Http_NEWLINE;
            // step3 --- 空行
            ret += _blankline;
            // step3 --- 正文
            ret += _data;
            return ret;
        }

    private:
        std::string _version;                                 // 版本号
        int _status;                                          // 状态码
        std::string _describe;                                // 状态情况
        std::unordered_map<std::string, std::string> _header; // 请求报头
        std::string _blankline = Http_NEWLINE;                // 空行
        std::string _data;                                    // 正文
    };

    class Http
    {
        bool ReadFile(const std::string &uri, int &size, std::string &in)
        {
            std::ifstream ifs(uri.c_str(), std::ios_base::in | std::ios_base::binary);
            if (!ifs)
                return false;

            ifs.seekg(0, std::ios::end);
            size = ifs.tellg();
            ifs.seekg(0, std::ios::beg);

            in.resize(size);
            if (!ifs.read((char *)in.c_str(), size))
                return false;

            return true; // 全部成功
        }

    public:
        Http()
        {
            // 目前硬编码常见的类型的Content_type
            // 后绪优化,可从文件中进行读取
            _suffix[".htm"] = "text/html";
            _suffix[".html"] = "text/html";
            _suffix[".ico"] = "image/x-icon";
            _suffix[".png"] = "image/png";
            _suffix[".jpg"] = "image/jpeg";
        }
        void GetRequest(std::shared_ptr<zmh::Socket> Socket /*, const std::function<Response(Request)> &func*/)
        {
            std::string buffer;   // 提供缓冲区
            Socket->recv(buffer); // 如何确保读取报文的完整性？？？

            Request req;
            req.Deserialize(buffer);

            std::string uri = req.get_uri();
            std::string data;
            int len = 0;
            if (ReadFile(uri, len, data))
            {
                // 读取成功
                Response res;
                res.init_version("HTTP/1.1");
                res.init_status(200);
                res.init_data(data);

                res.init_header("Content_Length", std::to_string(len));
                int pos = uri.rfind(".");
                res.init_header("Content_Type", _suffix[uri.substr(pos)]);

                std::string mes = res.Serialize();
                Send(Socket, mes);
            }
            else
            {
                // // 读取失败 --- 重定向到404
                // Response res;
                // res.init_version("HTTP/1.1");
                // res.init_status(302);

                // res.init_header("Location", "./Webroot/404.html");

                // std::string mes = res.Serialize();
                // Send(Socket, mes);
            }
        }

        void Send(std::shared_ptr<zmh::Socket> Socket, std::string message)
        {
            if (Socket->send(message) == -1)
                LOG(ERROR) << "Socket->send(message) mistake";
        }

    private:
        std::unordered_map<std::string, std::string> _suffix;
    };
}